----------Stickybear Opposites---------
A 4am crack                  2017-04-23
---------------------------------------

Name: Stickybear Opposites
Version: 13-JUL-1989 (based on ProDOS
  disk catalog)
Genre: educational
Year: 1989
Publisher: Optimum Resource
Platform: Apple ][+ or later (64K)
Media: single-sided 5.25-inch floppy
OS: ProDOS 1.5
Previous cracks: none
Similar cracks:
  #1163 Stickybear Shapes v03-FEB-89
  #1147 Stickybear Numbers v18-JAN-89

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  read error on second pass

Locksmith Fast Disk Backup
  unable to read T07,S0F
  copy boots ProDOS then crashes into
  the monitor at address $0002

EDD 4 bit copy (no sync, no count)
  works

Copy ][+
  "Disk Map" shows that T07,S0F is
  marked as used but is suspiciously
  unused by any actual files

                 --v--

DISK MAP                SLOT 6  DRIVE 1
/OPPOSITES/OPPOSITES

   TRACK           1               2
   0123456789ABCDEF0123456789ABCDEF012

S0 ........***************************
EE ........***************************
CD ........***************************
TC ........***************************
OB .......****************************
RA .......****************************
 9 .......****************************
 8 .......****************************
 7 .......****************************
 6 .......****************************
 5 .......***************************.
 4 .......***************************.
 3 .......***************************.
 2 .......***************************.
 1 ........**************************.
 F ........**************************.

   USE ARROW KEYS TO MAP OTHER FILES

                 --^--

Why didn't COPYA work?
  intentionally corrupted sector on
  track 7

Why didn't Locksmith FDB work?
  ditto

EDD worked. What does that tell us?
  No half or quarter tracks, because I
  didn't even try to copy those. There
  is definitely a run-time protection
  check of some kind, but it's probably
  just checking that that one sector on
  track 7 is unreadable. Since ProDOS
  loads, the check code is probably in
  the first .SYSTEM file.

Next steps:

  1. Search disk for common elements of
     a run-time protection check
  2. If that fails, trace the boot
  3. If that fails, I dunno, go eat
     fries for breakfast or something

                   ~

               Chapter 1
        In Which We Get Lucky,
   Then Celebrate With Fries Anyway


On the theory that some code on disk is
trying to access T07,S0F, and thus
noticing if it's unexpectedly readable,
let's enumerate some of the ways that
could happen:

- Reading a file that is mapped to the
  unreadable sector. Copy II+ "disk
  map" shows there are no files mapped
  to T07,S0F, so let's rule that out.

- Manually seeking to the track and
  looking for a nibble sequence. There
  is no explicit support for "seeking
  to a particular track" unless you're
  calling ProDOS internals. Without
  calling into ProDOS, this technique
  would require low-level disk access
  (turning on the drive and hitting the
  right stepper motors and whatnot).
  Here are some possibilities:

  "BD 89 C0" (LDA $C089,X)   ; drive on
  "AD E9 C0" (LDA $C0E9)     ; drive on
  "BD 80 C0" (LDA $C080,X)   ; stepper

  Searching for these common opcodes
  yield no suspicious-looking results.
  (There are matches inside legitimate
  RWTS code in the PRODOS system.)

- Issuing a ProDOS MLI "raw block read"
  and checking the return code. This is
  a popular technique under ProDOS,
  partly because it can be adapted to
  work on 3.5-inch and 5.25-inch disks.
  A sector search for "20 00 BF 80" (a
  to the standard ProDOS MLI entry
  point, with command $80 for a raw
  block read) yields two results:

                 --v--

------------- DISK SEARCH -------------

$00/$01-$E0   $03/$07-$09


             PRESS [RETURN]

                 --^--

T03,S07 is an expected part of the
PRODOS file. That leaves T00,S01.

Copy II Plus says that's part of the
file LOADER.SYSTEM, which would fit my
theory that there's a runtime check in
the first .SYSTEM file.

Switching over to the BASIC prompt, I
can load up LOADER.SYSTEM and see what
is going on.

                   ~

               Chapter 1
      In Which It All Comes Down
              To One Byte


[S7,D1=ProDOS hard drive, "A4AMCRACK"]
[S6,D1=non-working copy]

]PR#7
...

            PRODOS BASIC 1.6
        COPYRIGHT APPLE  1983-92

]CAT,S6,D1

/OPPOSITES

 NAME           TYPE  BLOCKS  MODIFIED

 LOADER.SYSTEM   SYS       3  13-JUL-89
 SAY             BIN      16  13-JUL-89
 PRODOS          SYS      32  17-MAR-88
 OPPOSITES       BIN     218   7-FEB-89
 FINDER.DATA     $C9       1   3-AUG-89

BLOCKS FREE:    2     BLOCKS USED:  278

]PREFIX /OPPOSITES
]BLOAD LOADER.SYSTEM,A$2000,TSYS
]CALL-151

*2000L

2000-   A9 00       LDA   #$00
2002-   85 50       STA   $50
2004-   A9 02       LDA   #$02

; machine identification (not shown)
2006-   20 BD 21    JSR   $21BD

; more machine identification
2009-   AD 98 BF    LDA   $BF98
200C-   29 30       AND   #$30
200E-   C9 30       CMP   #$30
2010-   D0 17       BNE   $2029

; even more machine ID (seems to be
; looking for some sort of peripheral
; card in slot 2 -- maybe a voice
; card?)
2012-   AD 05 C2    LDA   $C205
2015-   0D 07 C2    ORA   $C207
2018-   C9 38       CMP   #$38
201A-   D0 0A       BNE   $2026
201C-   AD 11 C2    LDA   $C211
201F-   F0 05       BEQ   $2026
2021-   20 E7 20    JSR   $20E7
2024-   90 03       BCC   $2029
2026-   20 29 21    JSR   $2129

; well this part is very interesting
2029-   20 E0 20    JSR   $20E0
202C-   D0 03       BNE   $2031

; a jump to nowhere (AFAICT the address
; is never modified)
202E-   4C 00 00    JMP   $0000

Now we're getting somewhere. So what's
at $20E0 that needs to return non-zero
in the accumulator to avoid jumping to
nowhere and crashing?

*20E0L

; call ProDOS MLI
20E0-   20 00 BF    JSR   $BF00
20E3-  [80]       ; READ_BLOCK command
20E4-  [87 20]    ; MLI parameter table
20E6-   60          RTS

That's it. A raw block read command.
And what are we reading? I'm glad you
asked.

*2087.

      +--- MLI parameter count
      |  +--- slot/drive (S6,D1)
      |  |  +--- address ($BB00)
      |  |  |     +--- block number
      v  v  v     v
2087- 03 60 00 BB 3F 00

Block #$003F would put us smack dab
onto... track $07, sector $0F.

Returning to the caller, all we're
doing is looking at the return code in
the accumulator after the MLI call:

202C-   D0 03       BNE   $2031
202E-   4C 00 00    JMP   $0000
...

If the accumulator is 0, that means the
READ_BLOCK call succeeded. Anything
else is an error code. But the caller
doesn't even care what the error is, as
long as there is one.

That gives me an idea.

A simple trick I've used on other disks
is to change the MLI command from
READ_BLOCK to CLOSE_ALL_FILES. Why?
Because the CLOSE_ALL_FILES command
takes a different number of parameters
in the MLI parameter table (1 instead
of 3), so the call always fails with
return code #$04 ("incorrect parameter
count"). And that's the behavior we
want! We want the MLI call to always
fail! Failure is success!

T00,S01,$E3: 80 -> CC

]PR#6
...works, and it is glorious...

The other advantage of this patch is
that you can copy all the files on the
disk onto a directory on your ProDOS
hard drive (you DO have a ProDOS hard
drive, don't you?) and the program will
work without modification. It doesn't
even do any weird raw block reads of
your hard drive, since we just changed
the weird block read to a harmless MLI
call that always fails.

Quod erat liberandum.

---------------------------------------
A 4am crack                    No. 1164
------------------EOF------------------
